package com.sky.service.impl;


import cn.mybatis.mp.core.mybatis.mapper.context.Pager;
import cn.mybatis.mp.core.sql.executor.chain.QueryChain;
import com.sky.dto.GetScripsDTO;
import com.sky.dto.SaveOrUpdataScriptDTO;
import com.sky.dto.SaveScriptPlayerCountsListDTO;
import com.sky.dto.ScriptTagRelationsDTO;
import com.sky.entity.Categories;
import com.sky.entity.ScriptPlayerCounts;
import com.sky.entity.ScriptTagRelations;
import com.sky.entity.Scripts;
import com.sky.entity.Tags;
import com.sky.exception.BaseException;
import com.sky.mapper.ScriptPlayerCountsMapper;
import com.sky.mapper.ScriptTagRelationsMapper;
import com.sky.mapper.ScriptsMapper;
import com.sky.mapper.TagsMapper;
import com.sky.mapper.CategoriesMapper;
import com.sky.service.CategoriesService;
import com.sky.service.ScriptPlayerCountsService;
import com.sky.service.ScriptTagRelationsService;
import com.sky.service.ScriptsService;
import com.sky.service.TagsService;
import com.sky.vo.GetScripsVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author majun
 * @package com.sky.service.impl
 * @date 2025/6/21 12:10
 */

@Service
public class ScriptsServiceImpl implements ScriptsService {

    @Autowired
    private ScriptsMapper scriptsMapper;

    @Autowired
    private CategoriesService categoriesService;

    @Autowired
    private ScriptPlayerCountsMapper scriptPlayerCountsMapper;

    @Autowired
    private ScriptTagRelationsMapper scriptTagRelationsMapper;

    @Autowired
    private TagsService tagsService;

    @Autowired
    private TagsMapper tagsMapper;

    @Autowired
    private CategoriesMapper categoriesMapper;

    @Autowired
    private ScriptPlayerCountsService scriptPlayerCountsService;

    @Autowired
    private ScriptTagRelationsService scriptTagRelationsService;

    /**
     * 保存剧本
     *
     * @param script 剧本内容
     */
    @Transactional
    public void saveScripts(Scripts script) {
        if (script == null) {
            throw new BaseException("剧本对象不能为空");
        }

        if (StringUtils.isEmpty(script.getName())) {
            throw new BaseException("剧本名称不能为空");
        }
        if (StringUtils.isEmpty(script.getAuthor())) {
            throw new BaseException("作者信息不能为空");
        }
        if (StringUtils.isEmpty(script.getCoverImage())) {
            throw new BaseException("封面图片不能为空");
        }
        if (script.getPricePerUser() == null) {
            throw new BaseException("价格信息不能为空");
        }
        if (StringUtils.isEmpty(script.getDuration())) {
            throw new BaseException("时长信息不能为空");
        }
        if (StringUtils.isEmpty(script.getLevel())) {
            throw new BaseException("难度等级不能为空");
        }
        if (StringUtils.isEmpty(script.getDescription())) {
            throw new BaseException("描述信息不能为空");
        }
        if (script.getIsTop() == null) {
            throw new BaseException("是否置顶标记不能为空");
        }
        if (script.getIsNew() == null) {
            throw new BaseException("是否新品标记不能为空");
        }
        if (script.getCategoryId() == null) {
            throw new BaseException("分类ID不能为空");
        }

        scriptsMapper.save(script);
    }

    /**
     * 新增或更新剧本
     *
     * @param saveOrUpdataScriptDTO 剧本数据
     */
    @Transactional
    public void saveOrUpdateScript(SaveOrUpdataScriptDTO saveOrUpdataScriptDTO) {
        if (saveOrUpdataScriptDTO == null) {
            throw new BaseException("剧本数据不能为空");
        }

        // 参数验证
        if (StringUtils.isEmpty(saveOrUpdataScriptDTO.getName())) {
            throw new BaseException("剧本名称不能为空");
        }
        if (StringUtils.isEmpty(saveOrUpdataScriptDTO.getAuthor())) {
            throw new BaseException("作者信息不能为空");
        }
        if (StringUtils.isEmpty(saveOrUpdataScriptDTO.getCoverImage())) {
            throw new BaseException("封面图片不能为空");
        }
        if (saveOrUpdataScriptDTO.getPricePerUser() == null) {
            throw new BaseException("价格信息不能为空");
        }
        if (StringUtils.isEmpty(saveOrUpdataScriptDTO.getDuration())) {
            throw new BaseException("时长信息不能为空");
        }
        if (StringUtils.isEmpty(saveOrUpdataScriptDTO.getLevel())) {
            throw new BaseException("难度等级不能为空");
        }
        if (StringUtils.isEmpty(saveOrUpdataScriptDTO.getDescription())) {
            throw new BaseException("描述信息不能为空");
        }
        if (saveOrUpdataScriptDTO.getIsTop() == null) {
            throw new BaseException("是否置顶标记不能为空");
        }
        if (saveOrUpdataScriptDTO.getIsNew() == null) {
            throw new BaseException("是否新品标记不能为空");
        }
        if (saveOrUpdataScriptDTO.getIsLimited() == null) {
            throw new BaseException("是否城限标记不能为空");
        }
        if (StringUtils.isEmpty(saveOrUpdataScriptDTO.getCategory())) {
            throw new BaseException("分类不能为空");
        }
        if (StringUtils.isEmpty(saveOrUpdataScriptDTO.getSupportCount())) {
            throw new BaseException("支持人数不能为空");
        }

        // 根据分类名称获取分类ID
        Categories category = categoriesService.getCategoriesByName(saveOrUpdataScriptDTO.getCategory());
        if (category == null) {
            throw new BaseException("分类不存在：" + saveOrUpdataScriptDTO.getCategory());
        }

        // 构建Scripts实体
        Scripts script = new Scripts();
        script.setId(saveOrUpdataScriptDTO.getId());
        script.setName(saveOrUpdataScriptDTO.getName());
        script.setAuthor(saveOrUpdataScriptDTO.getAuthor());
        script.setCoverImage(saveOrUpdataScriptDTO.getCoverImage());
        script.setPricePerUser(saveOrUpdataScriptDTO.getPricePerUser());
        script.setDuration(saveOrUpdataScriptDTO.getDuration());
        script.setLevel(saveOrUpdataScriptDTO.getLevel());
        script.setDescription(saveOrUpdataScriptDTO.getDescription());
        script.setIsTop(saveOrUpdataScriptDTO.getIsTop());
        script.setIsNew(saveOrUpdataScriptDTO.getIsNew());
        script.setIsLimited(saveOrUpdataScriptDTO.getIsLimited());
        script.setCategoryId(category.getId());

        // 判断是新增还是更新
        if (script.getId() != null) {
            // 更新剧本
            Scripts existingScript = scriptsMapper.getById(script.getId());
            if (existingScript == null) {
                throw new BaseException("剧本不存在，ID: " + script.getId());
            }
            scriptsMapper.update(script);
        } else {
            // 新增剧本
            scriptsMapper.save(script);
        }

        // 保存支持人数
        if (saveOrUpdataScriptDTO.getSupportCount() != null && saveOrUpdataScriptDTO.getSupportCount().length > 0) {
            SaveScriptPlayerCountsListDTO playerCountsDTO = new SaveScriptPlayerCountsListDTO();
            playerCountsDTO.setScriptId(script.getId().toString());
            String[] playerCounts = new String[saveOrUpdataScriptDTO.getSupportCount().length];
            for (int i = 0; i < saveOrUpdataScriptDTO.getSupportCount().length; i++) {
                playerCounts[i] = saveOrUpdataScriptDTO.getSupportCount()[i].toString();
            }
            playerCountsDTO.setPlayerCount(playerCounts);
            scriptPlayerCountsService.saveScriptPlayerCountsList(playerCountsDTO);
        }

        // 保存标签关系
        if (saveOrUpdataScriptDTO.getTagName() != null && saveOrUpdataScriptDTO.getTagName().length > 0) {
            // 根据标签名称获取标签ID
            List<Long> tagIds = new ArrayList<>();
            for (String tagName : saveOrUpdataScriptDTO.getTagName()) {
                Tags tag = tagsService.getTagsByNameExact(tagName);
                if (tag == null) {
                    throw new BaseException("标签不存在：" + tagName);
                }
                tagIds.add(tag.getId());
            }

            ScriptTagRelationsDTO tagRelationsDTO = new ScriptTagRelationsDTO();
            tagRelationsDTO.setScriptId(script.getId());
            tagRelationsDTO.setTagId(tagIds.toArray(new Long[0]));
            scriptTagRelationsService.save(tagRelationsDTO);
        }
    }

    /**
     * 根据id查询剧本
     *
     * @param id 剧本id
     * @return 剧本内容
     */
    public Scripts getScriptsById(Long id) {
        return scriptsMapper.getById(id);
    }

    /**
     * 获取剧本列表
     * @param getScripsDTO 获取剧本参数
     * @return 剧本列表
     */
    public Pager<GetScripsVO> getScrips(GetScripsDTO getScripsDTO) {
        
        QueryChain<Scripts> queryChain = QueryChain.of(scriptsMapper);
        
        // 剧本名称模糊查询
        if (StringUtils.hasText(getScripsDTO.getName())) {
            queryChain.like(Scripts::getName, getScripsDTO.getName());
        }
        
        // 分类筛选
        if (StringUtils.hasText(getScripsDTO.getCategoryName())) {
            Categories category = QueryChain.of(categoriesMapper)
                    .eq(Categories::getName, getScripsDTO.getCategoryName())
                    .get();
            
            if (category == null) {
                // 返回空的分页结果
                return createEmptyPager(getScripsDTO);
            }
            
            queryChain.eq(Scripts::getCategoryId, category.getId());
        }
        
        // 支持人数筛选
        if (getScripsDTO.getSupportCount() != null) {
            List<ScriptPlayerCounts> playerCounts = QueryChain.of(scriptPlayerCountsMapper)
                    .eq(ScriptPlayerCounts::getPlayerCount, getScripsDTO.getSupportCount())
                    .list();
            
            if (playerCounts.isEmpty()) {
                // 返回空的分页结果
                return createEmptyPager(getScripsDTO);
            }
            
            List<Long> scriptIds = playerCounts.stream()
                    .map(ScriptPlayerCounts::getScriptId)
                    .toList();
            queryChain.in(Scripts::getId, scriptIds);
        }
        
        // 标签筛选
        if (StringUtils.hasText(getScripsDTO.getTagName())) {
            Tags tag = QueryChain.of(tagsMapper)
                    .eq(Tags::getName, getScripsDTO.getTagName())
                    .get();
            
            if (tag == null) {
                // 返回空的分页结果
                return createEmptyPager(getScripsDTO);
            }
            
            List<ScriptTagRelations> relations = QueryChain.of(scriptTagRelationsMapper)
                    .eq(ScriptTagRelations::getTagId, tag.getId())
                    .list();
            
            if (relations.isEmpty()) {
                // 返回空的分页结果
                return createEmptyPager(getScripsDTO);
            }
            
            List<Long> scriptIds = relations.stream()
                    .map(ScriptTagRelations::getScriptId)
                    .toList();
            queryChain.in(Scripts::getId, scriptIds);
        }
        
        queryChain.orderByDesc(Scripts::getCreatedAt);
        
        // 分页参数
        int pageNo = getScripsDTO.getPageNo() != null ? getScripsDTO.getPageNo() : 1;
        int pageSize = getScripsDTO.getPageSize() != null ? getScripsDTO.getPageSize() : 10;
        
        // 执行分页查询
        Pager<Scripts> pageResult = queryChain.paging(Pager.of(pageNo, pageSize));
        
        // 转换为 VO
        List<GetScripsVO> voList = pageResult.getResults().stream()
                .map(this::convertToVO)
                .toList();
        
        // 封装 VO 的分页结果
        Pager<GetScripsVO> voPager = Pager.of(pageNo, pageSize);
        voPager.setTotal(pageResult.getTotal());
        voPager.setResults(voList);
        
        return voPager;
    }

    /**
     * 获取剧本杀详情
     * @param id 剧本id
     * @return 剧本详情
     */
    public GetScripsVO getScriptsByIdVO(Long id) {
        Scripts script = getScriptsById(id);
        if (script == null) {
            return null;
        }
        return convertToVO(script);
    }

    /**
     * 创建空的分页结果
     * @param getScripsDTO 查询参数
     * @return 空的分页结果
     */
    private Pager<GetScripsVO> createEmptyPager(GetScripsDTO getScripsDTO) {
        int pageNo = getScripsDTO.getPageNo() != null ? getScripsDTO.getPageNo() : 1;
        int pageSize = getScripsDTO.getPageSize() != null ? getScripsDTO.getPageSize() : 10;
        
        Pager<GetScripsVO> emptyPager = Pager.of(pageNo, pageSize);
        emptyPager.setTotal(0);
        emptyPager.setResults(Collections.emptyList());
        
        return emptyPager;
    }
    
    /**
     * 将 Scripts 实体转换为 GetScripsVO
     */
    private GetScripsVO convertToVO(Scripts script) {
        GetScripsVO vo = new GetScripsVO();
        vo.setId(script.getId());
        vo.setName(script.getName());
        vo.setAuthor(script.getAuthor());
        vo.setCoverImage(script.getCoverImage());
        vo.setPricePerUser(script.getPricePerUser());
        vo.setDuration(script.getDuration());
        vo.setLevel(script.getLevel());
        vo.setDescription(script.getDescription());
        vo.setIsTop(script.getIsTop());
        vo.setIsNew(script.getIsNew());
        vo.setIsLimited(script.getIsLimited());
        
        // 获取分类名称
        if (script.getCategoryId() != null) {
            Categories category = categoriesService.getCategoriesById(script.getCategoryId());
            if (category != null) {
                vo.setCategory(category.getName());
            }
        }
        
        // 获取支持人数
        List<ScriptPlayerCounts> playerCounts = QueryChain.of(scriptPlayerCountsMapper)
                .eq(ScriptPlayerCounts::getScriptId, script.getId())
                .list();
        
        if (!playerCounts.isEmpty()) {
            Integer[] supportCounts = playerCounts.stream()
                    .map(ScriptPlayerCounts::getPlayerCount)
                    .toArray(Integer[]::new);
            vo.setSupportCount(supportCounts);
        }
        
        // 获取标签名称
        List<ScriptTagRelations> relations = QueryChain.of(scriptTagRelationsMapper)
                .eq(ScriptTagRelations::getScriptId, script.getId())
                .list();
        
        if (!relations.isEmpty()) {
            List<String> tagNames = new ArrayList<>();
            for (ScriptTagRelations relation : relations) {
                Tags tag = tagsService.getTagsById(relation.getTagId());
                if (tag != null) {
                    tagNames.add(tag.getName());
                }
            }
            vo.setTagName(tagNames.toArray(new String[0]));
        }
        
        return vo;
    }

    /**
     * 删除剧本
     * @param id 剧本id
     */
    @Transactional
    public void deleteScript(Long id) {
        // 检查剧本是否存在
        Scripts script = getScriptsById(id);
        if (script == null) {
            throw new BaseException("剧本不存在");
        }

        // 删除剧本支持人数记录
        List<ScriptPlayerCounts> playerCounts = QueryChain.of(scriptPlayerCountsMapper)
                .eq(ScriptPlayerCounts::getScriptId, id)
                .list();
        
        for (ScriptPlayerCounts playerCount : playerCounts) {
            scriptPlayerCountsMapper.deleteById(playerCount.getId());
        }

        // 删除剧本标签关联记录
        List<ScriptTagRelations> tagRelations = QueryChain.of(scriptTagRelationsMapper)
                .eq(ScriptTagRelations::getScriptId, id)
                .list();
        
        for (ScriptTagRelations tagRelation : tagRelations) {
            scriptTagRelationsMapper.deleteById(tagRelation.getId());
        }

        // 删除剧本本身
        scriptsMapper.deleteById(id);
    }

}
